home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl2 / examples / stencil / csg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  8.2 KB  |  329 lines

  1. /*
  2.  * Copyright 1993, 1995, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* csg.c 
  19.  * This program demonstrate constructive solid geometry.
  20.  * 
  21.  *    Escape key    - exit the program
  22.  *    <r> key        - toggle rotation
  23.  */
  24. #include <GL/gl.h>
  25. #include <GL/glu.h>
  26. #include <GL/glut.h>
  27.  
  28. #include <math.h>
  29. #include <stdio.h>
  30.  
  31. /* Function Prototypes */
  32.  
  33. GLvoid  initgfx( GLvoid );
  34. GLvoid  drawScene( GLvoid );
  35. GLvoid  reshape( GLsizei, GLsizei );
  36. GLvoid  animate( GLvoid );
  37. GLvoid  visibility( GLint );
  38. GLvoid  keyboard( GLubyte, GLint, GLint );
  39.  
  40. GLvoid    drawCylinder( GLint );
  41. GLvoid  screenRectangle( GLvoid );
  42. GLvoid    solidCylinder( GLfloat, GLfloat, GLint );
  43.  
  44. void printHelp( char * );
  45.  
  46. /* Global Definitions */
  47.  
  48. #define KEY_ESC    27    /* ascii value for the escape key */
  49.  
  50. /* Global Variables */
  51.  
  52. static GLfloat        fovy = 60.0;    /* Field of view in Y angle */
  53. static GLfloat        near = 3.0;    /* Near clipping plane location */
  54. static GLfloat        far  = 13.0;    /* Far clipping plane location */
  55.  
  56. static GLfloat        spin = 0.0;
  57.  
  58. void
  59. main(int argc, char *argv[])
  60. {
  61.     GLsizei     width, height;
  62.  
  63.     glutInit( &argc, argv );
  64.  
  65.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  66.     height = glutGet( GLUT_SCREEN_HEIGHT );
  67.     glutInitWindowPosition( width/4, height/4 ); 
  68.     glutInitWindowSize( width/2, height/2 );
  69.     glutInitDisplayMode( GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE|GLUT_STENCIL );
  70.     glutCreateWindow( argv[0] );
  71.     
  72.     initgfx();
  73.  
  74.     glutKeyboardFunc( keyboard );
  75.     glutReshapeFunc( reshape );
  76.     glutIdleFunc( animate ); 
  77.     glutVisibilityFunc( visibility ); 
  78.     glutDisplayFunc( drawScene ); 
  79.  
  80.     printHelp( argv[0] );
  81.  
  82.     glutMainLoop();
  83. }
  84.  
  85. void
  86. printHelp( char *progname )
  87. {
  88.     fprintf(stdout, "%s -- demonstrates how to use the stencil planes\n"
  89.         "to perform constructive solid geometry\n\n"
  90.         "Escape key    - exit the program\n"
  91.         "<r> key        - toggle rotation\n\n", progname);
  92. }
  93.  
  94. /*  Initialize material properties, light source, lighting model, etc. */
  95. GLvoid
  96. initgfx( GLvoid )
  97. {
  98.     GLfloat mat_ambient[] = { 0.25, 0.05, 0.4, 1.0 };
  99.     GLfloat mat_diffuse[] = { 0.5, 0.1, 0.8, 1.0 };
  100.     GLfloat mat_diffuse_back[] = { 1.0, 1.0, 0.0, 1.0 };
  101.     GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  102.     GLfloat mat_shininess[] = { 10.0 };
  103.     GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
  104.  
  105.     glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  106.     glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
  107.     glMaterialfv(GL_BACK, GL_DIFFUSE, mat_diffuse_back);
  108.     glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  109.     glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  110.     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  111.  
  112.     glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
  113.  
  114.     glEnable(GL_LIGHTING);
  115.     glEnable(GL_LIGHT0);
  116.  
  117.     glEnable( GL_DEPTH_TEST );
  118. }
  119.  
  120. GLvoid 
  121. keyboard( GLubyte key, GLint x, GLint y )
  122. {
  123.     static GLboolean rotating = GL_TRUE;
  124.  
  125.     switch (key) {
  126.     case 'r':    /* toggle rotation */
  127.         rotating = !rotating;
  128.         if (rotating)
  129.             glutIdleFunc( animate );
  130.         else 
  131.             glutIdleFunc( NULL );
  132.         break;
  133.     case KEY_ESC:    /* Exit whenever the Escape key is pressed */
  134.         exit(0);
  135.     }
  136. }
  137.  
  138. GLvoid
  139. reshape( GLsizei width, GLsizei height )
  140. {
  141.     glViewport( 0, 0, width, height );
  142.     glMatrixMode( GL_PROJECTION );
  143.     glLoadIdentity();
  144.     gluPerspective( fovy, (GLdouble) width / (GLdouble) height, near, far );
  145.     glMatrixMode( GL_MODELVIEW );
  146.     gluLookAt( 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
  147. }
  148. GLvoid
  149. animate( GLvoid )
  150. {
  151.     spin = fmodf( spin + 3.0, 360.0 );    /* update spin */
  152.     glutPostRedisplay();            /* Tell GLUT to redraw */
  153. }
  154.         
  155. GLvoid
  156. visibility( int state )
  157. {
  158.     if (state == GLUT_VISIBLE) {
  159.         glutIdleFunc( animate );
  160.     } else {
  161.         glutIdleFunc( NULL );
  162.     }
  163. }
  164.  
  165. /* solidCylinder -- draws a filled cylinder. If the closed flag
  166.  * is set, it cap the ends, making it a closed cylinder.
  167.  * The glutSolidCylinder routine is not appropriate here because 
  168.  * it does not cap its ends.
  169.  */
  170. #define NSEG 20
  171. #define TP (2.*M_PI) /* 2*pi */
  172.  
  173. GLvoid
  174. solidCylinder( GLfloat radius, GLfloat length, GLint closed )
  175. {
  176.     GLfloat circleCoords[NSEG][2], n[NSEG][3];
  177.     int i;
  178.  
  179.     /* define circle coords and draw sides of cylinder */
  180.     glBegin (GL_QUAD_STRIP);
  181.         for (i=0; i<NSEG; i++) {
  182.             n[i][0] = sinf((float)i/NSEG*TP);
  183.             n[i][1] = cosf((float)i/NSEG*TP);
  184.             n[i][2] = 0;
  185.             circleCoords[i][0] = n[i][0] * radius;
  186.             circleCoords[i][1] = n[i][1] * radius;
  187.             glNormal3fv( n[i] );
  188.             glVertex3f( circleCoords[i][0], circleCoords[i][1], 
  189.                     -length/2.0 );
  190.             glVertex3f( circleCoords[i][0], circleCoords[i][1], 
  191.                     length/2.0 );
  192.         }
  193.         glNormal3fv(n[0] );
  194.         glVertex3f( circleCoords[0][0], circleCoords[0][1], 
  195.                 -length/2.0 );
  196.         glVertex3f( circleCoords[0][0], circleCoords[0][1], 
  197.                 length/2.0 );
  198.     glEnd();
  199.  
  200.     if ( closed ) {
  201.         /* draw bottom (-z) end of cylinder */
  202.         glNormal3f(0, 0, -1);
  203.         glBegin (GL_POLYGON);
  204.         for(i=0; i<NSEG; i++) {
  205.             glVertex3f( circleCoords[i][0], circleCoords[i][1], 
  206.                 -length/2.0 );
  207.         }
  208.         glEnd();
  209.  
  210.         /* other end of cylinder */
  211.         glNormal3f(0, 0, 1);
  212.         glBegin (GL_POLYGON);
  213.         for(i=0; i<NSEG; i++) {
  214.             glVertex3f( circleCoords[NSEG-1-i][0], 
  215.                 circleCoords[NSEG-1-i][1], length/2.0 );
  216.         }
  217.         glEnd();
  218.     }
  219. }
  220.  
  221. GLvoid
  222. drawCylinder( GLint closed )
  223. {
  224.     glPushMatrix();
  225.         glRotatef( 90, 0.0, 0.0, 1.0 );
  226.         solidCylinder( 0.3, 2.0, closed );
  227.     glPopMatrix();
  228. }
  229.  
  230. /* draw a rectangle the size of the screen */
  231. GLvoid
  232. screenRectangle( GLvoid )
  233. {
  234.     GLint viewport[4];
  235.  
  236.     glGetIntegerv( GL_VIEWPORT, viewport );
  237.     glPushMatrix();
  238.         glLoadIdentity();
  239.         glMatrixMode( GL_PROJECTION );
  240.         glPushMatrix();
  241.             glLoadIdentity();
  242.             gluOrtho2D(0, viewport[2], 0, viewport[3] );
  243.             glRecti( 0, 0, viewport[2], viewport[3] );
  244.         glPopMatrix();
  245.         glMatrixMode( GL_MODELVIEW );
  246.     glPopMatrix();
  247. }
  248.  
  249. GLvoid
  250. drawScene( GLvoid )
  251. {
  252.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
  253.         GL_STENCIL_BUFFER_BIT );
  254.  
  255.     glPushMatrix();
  256.     glRotatef( spin, 0.0, 1.0, 0.0 );
  257.  
  258.     /* disable writing to color planes until we're ready to draw */
  259.     glColorMask ( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
  260.  
  261.     /* render the front faces of the tetrahedron into the depth planes, 
  262.      * capturing the depth info 
  263.      */
  264.  
  265.     glCullFace( GL_BACK );
  266.     glEnable( GL_CULL_FACE );
  267.     glDepthFunc( GL_LESS );  /* reset to default depth test */
  268.     glutSolidTetrahedron();
  269.  
  270.  
  271.     /* increment the stencil planes whereever either face 
  272.      * (front or back) of the cylinder is in front of the tetra 
  273.      * (the depth test passes), but don't update the depth buffer.
  274.      */
  275.  
  276.     glEnable( GL_STENCIL_TEST );
  277.     glStencilFunc( GL_ALWAYS, 0, 0xff );
  278.     glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
  279.     glDepthMask( 0 );
  280.     glDisable( GL_CULL_FACE );
  281.     drawCylinder( 1 );
  282.     glDepthMask( 1 ); /* reenable writing to the depth buffer */
  283.  
  284.     /* force depth values to max value wherever the cylinder is inside 
  285.      * the tetra (wherever the stencil planes have a value of one)
  286.      */
  287.  
  288.     glStencilFunc( GL_EQUAL, 1, 0xff );
  289.     glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
  290.     glDepthFunc( GL_ALWAYS );
  291.     glDepthRange( 1.0, 1.0 );
  292.     screenRectangle(); /* draw rectangle size of screen */
  293.     glDepthRange( 0.0, 1.0 );
  294.  
  295.     /* render back faces of the tetra and the (uncapped) cylinder
  296.      * into depth buffer where the hole is (the stencil test is 
  297.      * still active).  This will keep the cylinder from sticking 
  298.      * outside the tetra.
  299.      */
  300.  
  301.     glCullFace( GL_FRONT );
  302.     glEnable( GL_CULL_FACE );
  303.     glDepthFunc( GL_LESS );
  304.     glutSolidTetrahedron();
  305.     drawCylinder( 0 );
  306.  
  307.     /* now draw -- enable writing to the color bitplanes and 
  308.      * set the depth test to pass only if the incoming z equals 
  309.      * the stored z.  Turn off the stencil test.
  310.      */
  311.  
  312.     glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
  313.     glDisable( GL_STENCIL_TEST );
  314.     glCullFace( GL_BACK );
  315.     glDepthFunc( GL_EQUAL );
  316.     glutSolidTetrahedron();
  317.  
  318.     /* draw the back faces of the cylinder because we want to 
  319.      * see the inside of it.
  320.      */
  321.  
  322.     glCullFace( GL_FRONT );
  323.     drawCylinder( 0 );
  324.  
  325.     glPopMatrix();
  326.  
  327.     glutSwapBuffers();
  328. }
  329.